﻿// /************************************************************************/
// /*@Company           :
// /*@Author            :
// /*@FrameWork         : NET8
// /*@Company Web       :
// /*@Description       :
// /************************************************************************/

using Furion.Localization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Neto.Files;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Webp;
using System.IO;

namespace Neto.Core.CoreServices;

/// <summary>
///     系统文件服务
/// </summary>
public class SysFileService : ISysFileService, ITransient
{
    public ISqlSugarClient _db;

    public SysFileService(ISqlSugarClient db)
    {
        _db = db;
    }

    #region 文件格式转换

    /// <summary>
    ///     判断是不是tif
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    public bool IsTifImage(string filePath)
    {
        var extension = Path.GetExtension(filePath);

        if (string.Equals(extension, ".tif", StringComparison.OrdinalIgnoreCase) ||
            string.Equals(extension, ".tiff", StringComparison.OrdinalIgnoreCase))
            return true;

        return false;
    }

    /// <summary>
    ///     tif转化为png
    /// </summary>
    /// <param name="inputPath"></param>
    /// <param name="outputPath"></param>
    public async Task ConvertTifToPng(string inputPath, string outputPath)
    {
        using (var image = await SixLabors.ImageSharp.Image.LoadAsync(inputPath))
            image.Save(outputPath, new PngEncoder());
    }

    /// <summary>
    ///     tif转换为jpg
    /// </summary>
    /// <param name="inputPath"></param>
    /// <param name="outputPath"></param>
    public async Task ConvertTifToJpg(string inputPath, string outputPath)
    {
        using (var image = await SixLabors.ImageSharp.Image.LoadAsync(inputPath))
            image.Save(outputPath, new JpegEncoder());
    }

    /// <summary>
    ///     图片转换为webp
    /// </summary>
    /// <param name="inputPath"></param>
    /// <param name="outputPath"></param>
    public async Task ConvertTifToWebP(string inputPath, string outputPath)
    {
        using (var image = await SixLabors.ImageSharp.Image.LoadAsync(inputPath))
            image.Save(outputPath, new WebpEncoder());
    }

    #endregion

    #region 新版本文件上传

    /// <summary>
    ///     获取默认图片上传设置
    ///     允许上传的扩展：.jpg .png .jpeg .jif .bmp .webp
    ///     RelFileFloder=category
    /// </summary>
    /// <param name="category">分类</param>
    /// <param name="isOpen">是否公开</param>
    /// <param name="relRoutUrl">相对路径:默认f</param>
    /// <returns></returns>
    public FileUploadSetting GetDefaultImageSetting(string category, bool isOpen = false, string relRoutUrl = "f")
    {
        var uploadConfig = new WebUploadConfig(category, [".jpg", ".png", ".jpeg", ".jif", ".bmp", ".webp"])
        {
            RelFileFloder = category // 设置文件相对路径文件夹
        };
        // 创建文件上传设置
        var fileUploadSetting = new FileUploadSetting(uploadConfig, SysFileCatetoryType.logo, isOpen);
        return fileUploadSetting;
    }

    /// <summary>
    ///     获取默认富文本上传设置
    ///     允许上传的扩展：.jpg .png .jpeg .jif .bmp .webp .pdf .doc .docx .xls .xlsx .ppt .pptx .zip .rar
    ///     RelFileFloder=category
    /// </summary>
    /// <param name="category">分类</param>
    /// <param name="isOpen">是否公开</param>
    /// <param name="relRoutUrl">相对路径:默认f</param>
    /// <returns></returns>
    public FileUploadSetting GetDefaultRichtextSetting(string category, bool isOpen = false, string relRoutUrl = "f")
    {
        var uploadConfig =
            new WebUploadConfig(category,
            [
                ".jpg", ".png", ".jpeg", ".jif", ".bmp", ".webp", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt",
                ".pptx", ".zip", ".rar"
            ])
            {
                RelFileFloder = category, // 设置文件相对路径文件夹
                MaxFileSize = 20 //最大上传文件大小
            };
        // 创建文件上传设置
        var fileUploadSetting = new FileUploadSetting(uploadConfig, SysFileCatetoryType.logo, isOpen);
        return fileUploadSetting;
    }

    /// <summary>
    ///     上传单个文件。但是不保存到数据库
    /// </summary>
    /// <param name="fileUploadSetting"></param>
    /// <param name="file">要上传的文件，可选参数，默认为null。</param>
    /// <returns>返回上传结果。</returns>
    public async Task<WebUploadResult> GetUploadFile(FileUploadSetting fileUploadSetting, IFormFile file = null)
    {
        var uploadResult = await WebUpload.UploadFile(fileUploadSetting.UploadConfig, file);


        return uploadResult;
    }

    /// <summary>
    ///     上传单个文件。
    /// </summary>
    /// <param name="uploadConfig">上传配置信息。</param>
    /// <param name="fileUploadSetting"></param>
    /// <param name="file">要上传的文件，可选参数，默认为null。</param>
    /// <returns>返回上传结果。</returns>
    public async Task<WebUploadResult> UploadFile(FileUploadSetting fileUploadSetting,
        IFormFile? file = null)
    {
        var uploadResult = await WebUpload.UploadFile(fileUploadSetting.UploadConfig, file);

        // 如果上传成功，则将上传结果插入数据库
        if (uploadResult.Success) await InsertFile(fileUploadSetting, uploadResult);

        return uploadResult;
    }

    /// <summary>
    ///     上传多个文件。
    /// </summary>
    /// <param name="fileUploadSetting">上传配置信息。</param>
    /// <param name="files">要上传的文件列表，可选参数，默认为null。</param>
    /// <returns>返回上传结果列表。</returns>
    public async Task<List<WebUploadResult>> UploadFiles(FileUploadSetting fileUploadSetting,
        List<IFormFile?>? files = null)
    {
        var uploadResults = await WebUpload.UploadFiles(fileUploadSetting.UploadConfig, files);

        // 遍历上传成功的文件，并将其结果插入数据库
        foreach (var uploadResult in uploadResults.Where(uploadResult => uploadResult.Success))
            await InsertFile(fileUploadSetting, uploadResult);

        return uploadResults;
    }

    /// <summary>
    ///     将上传结果插入数据库。
    /// </summary>
    /// <param name="fileUploadSetting">上传配置信息。</param>
    /// <param name="uploadResult">上传结果信息。</param>
    /// <returns>返回插入数据库后的文件信息。</returns>
    private async Task<SysFiles> InsertFile(FileUploadSetting fileUploadSetting, WebUploadResult uploadResult)
    {
        var file = fileUploadSetting.Adapt<SysFiles>();

        #region 文件业务设置

        // file.CatetoryType = fileUploadSetting.CatetoryType;
        // file.Sort = fileUploadSetting.Sort;
        // file.Code = fileUploadSetting.Code;
        //file.IsOpen = fileUploadSetting.IsOpen;

        //file.Tags = fileUploadSetting.Tags;

        #endregion

        #region 上传文件配置来的

        // 设置文件的其他属性
        file.IsWwwroot = fileUploadSetting.UploadConfig.IsWwwroot; // 是否是wwwroot下的文件
        file.Category = fileUploadSetting.UploadConfig.Category; // 设置文件分类
        file.RelFileFloder = fileUploadSetting.UploadConfig.RelFileFloder; // 设置文件相对文件夹路径

        #endregion

        #region 上传结果设置

        // 设置文件ID，如果已有ID则使用原有ID，否则生成新的GUID
        if (!string.IsNullOrWhiteSpace(uploadResult.FId))
            file.FId = uploadResult.FId;
        else
            file.FId = Guid.NewGuid().ToString("N");


        file.Extension = uploadResult.Extension;
        file.FilePath = uploadResult.RelFilePath; // 设置文件的相对路径
        file.ImgFilePathThumbnail = uploadResult.ThumbnailRelFileName; // 设置图片文件的缩略图相对路径
        file.Name = uploadResult.UploadFilename; // 上传的文件名
        file.Size = uploadResult.FileSize_Byte;

        #endregion

        file.FileInfo = new SysFileInfo();

        // 在数据库中插入文件信息
        var result = await _db.InsertReturnEntityAsync(file);

        return result;
    }

    /// <summary>
    ///     根据文件ID异步获取文件，支持获取缩略图和指定文件是否公开。
    /// </summary>
    /// <param name="fid">文件ID</param>
    /// <param name="isThumbnail">是否获取缩略图</param>
    /// <param name="isOpen">是否公开的标志（可选）</param>
    /// <returns>返回文件内容结果，如果文件不存在或查询失败，则返回404内容。</returns>
    public async Task<IActionResult> GetFile(string fid, bool? isThumbnail = null, bool? isOpen = null)
    {
        // 异步获取系统文件信息
        var sysFile = await GetSysFile(fid, isOpen);
        if (sysFile == null)
            // 如果没有找到文件，则返回404
            return GetNotFoundContentResult();
        // 如果文件是存到wwwroot静态目录中，则从wwwroot目录中获取文件
        if (sysFile.IsWwwroot)
        {
            // 获取网站根目录wwwroot路径
            var rootPath = App.WebHostEnvironment?.WebRootPath ?? "";
            // 如果没有找到根目录，则返回404
            if (string.IsNullOrWhiteSpace(rootPath)) return GetNotFoundContentResult();

            // 根据是否需要缩略图，返回对应的文件
            return GetFile(sysFile, rootPath, isThumbnail);
        }
        else
        {
            // 获取上传文件夹路径
            var rootPath = WebUpload.GetFileUploadFloder();
            // 根据是否需要缩略图，返回对应的文件
            return GetFile(sysFile, rootPath, isThumbnail);
        }
    }

    /// <summary>
    ///     根据文件路径和是否需要缩略图，返回文件内容结果。
    /// </summary>
    /// <param name="sysFile">系统文件信息</param>
    /// <param name="rootPath">文件根路径</param>
    /// <param name="isThumbnail">是否需要缩略图</param>
    /// <returns>返回文件内容结果，如果文件不存在，则返回404内容。</returns>
    private IActionResult GetFile(SysFiles sysFile, string rootPath, bool? isThumbnail = null)
    {
        var fileFullPath = "";
        // 根据是否需要缩略图，构建文件完整路径
        if (isThumbnail != null && isThumbnail.Value && !string.IsNullOrWhiteSpace(sysFile.ImgFilePathThumbnail))
            fileFullPath = rootPath + Path.DirectorySeparatorChar + sysFile.ImgFilePathThumbnail;
        else
            fileFullPath = rootPath + Path.DirectorySeparatorChar + sysFile.FilePath;

        //处理文件路径
        fileFullPath = fileFullPath.ToOsDirectory();
        //var logger = AppEx.GetSeriLogger("file");
        //logger.Info(fileFullPath);
        // 检查文件是否存在
        if (!File.Exists(fileFullPath))
            // 如果文件不存在，则返回404
            return GetNotFoundContentResult();

        // 返回文件内容结果，包括文件类型和下载名称
        return new PhysicalFileResult(fileFullPath, fileFullPath.GetFileMimeType()) { FileDownloadName = sysFile.Name };
    }

    /// <summary>
    ///     创建并返回一个表示文件未找到的404内容结果。
    /// </summary>
    /// <returns>返回一个404内容结果。</returns>
    private ContentResult GetNotFoundContentResult()
    {
        var culture = L.GetSelectCulture().Culture.Name;
        ContentResult contentResult = null;
        if (culture == "en-Us")
            contentResult = new ContentResult { StatusCode = 404, Content = "File not found" };
        else
            contentResult = new ContentResult { StatusCode = 404, Content = L.Text["文件不存在"] };

        return contentResult;
    }


    /// <summary>
    ///     根据文件ID获取文件名。
    /// </summary>
    /// <param name="fid">文件ID</param>
    /// <returns>获取文件名</returns>
    public async Task<string> GetSysFileName(string fid)
    {
        // 构建查询条件
        var queryable = _db.Queryable<SysFiles>().Where(o => o.FId == fid);


        // 执行查询并返回结果
        var sysFile = await queryable.Select(o => o.Name).FirstAsync();
        return sysFile;
    }

    /// <summary>
    ///     根据文件ID和是否公开的标志异步查询系统文件信息。
    /// </summary>
    /// <param name="fid">文件ID</param>
    /// <param name="isOpen">是否公开的标志（可选）</param>
    /// <returns>返回查询到的第一个系统文件信息，如果未找到则返回null。</returns>
    private async Task<SysFiles> GetSysFile(string fid, bool? isOpen)
    {
        // 构建查询条件
        var queryable = _db.Queryable<SysFiles>().Where(o => o.FId == fid);
        if (isOpen.HasValue) queryable = queryable.Where(o => o.IsOpen == isOpen.Value);

        // 执行查询并返回结果
        var sysFile = await queryable.FirstAsync();
        return sysFile;
    }

    #endregion
}